package com.qingfeng.testandroid12sdkdemo.activity

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.qingfeng.basic_lib.basic.BasicApp
import com.qingfeng.testandroid12sdkdemo.R
import com.qingfeng.testandroid12sdkdemo.data.entity.UsedWeb
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.resumeCancellableWith
import java.util.concurrent.Executors
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
import kotlin.coroutines.*

class TestActivity : AppCompatActivity() {

    private val code = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
        val findViewById = findViewById<Button>(R.id.btn)
        val array = listOf("b", "c")
        val aBoolean = "a" in array
        val bBoolean = "a" !in array
        val cBoolean = "kot" in "abc".."xyz"
        for (s in array) {
            println(s)
        }
        for ((index, value) in array.withIndex()) {
            println("the element at $index is $value")
        }

//        MainScope().launch {
//            withContext(Dispatchers.IO) {
//                Thread.sleep(10_000)
//
//            }
//        }
//        Pair<Integer, Integer>
//        CompletableFuture

        val continuation = suspend {
            println("In Coroutine.")
            5
        }.createCoroutine(object : Continuation<Int> {
            override val context = EmptyCoroutineContext

            override fun resumeWith(result: Result<Int>) {
                println("Coroutine End: $result")
            }

        })


        val continuation1 = suspend {
            println("In Coroutine.")
            5
        }.startCoroutine(object : Continuation<Int> {
            override val context = EmptyCoroutineContext

            override fun resumeWith(result: Result<Int>) {
                println("Coroutine End: $result")
            }

        })


        findViewById.setOnClickListener {
//            val continuation = suspend {
//                println("In Coroutine.")
//                5
//            }.startCoroutine(object : Continuation<Int> {
//                override val context = LogInterceptor()
//
//                override fun resumeWith(result: Result<Int>) {
//                    println("Coroutine End: $result")
//                }
//
//            })
//            case1()
//            case1()
//            startCoroutines(it)
//            exceptionWithJob()
//            exceptionWithSupervisorJob()
//            jobSleepCancel()
//            cancelExceptionWithJob()
//            invokeCompletion()
//            testLaunch()
//            assert(code != 0)
//            invokeCancelCompletion()

            MainScope().launch {
                testUnderStandSuspend()
            }

        }




    }


    fun openPicture(){
        PictureSelector.create(this)
            .openGallery(PictureMimeType.ofImage())
            .isPreviewImage(true)
    }


    fun plusCase(){
        val case1 = Dispatchers.Main + EmptyCoroutineContext
        println("147114 case1 $case1")

        val case2 = CoroutineName("c1") + CoroutineName("c2")
        println("147114 case2 $case2")

        val case3 = CoroutineName("c1") + Job()
        println("147114 case3 $case3")

        val case4 = Dispatchers.Main + Job()
        println("147114 case4 $case4")

        val case5 = case4 + CoroutineName("c5")
        println("147114 case5 $case5")
    }

    fun startCoroutines(view: View){
        MainScope().launch {
            println("Hello Coroutines")
        }
    }

    fun testCoroutines(){
        val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
            println(
                "xiaozhan exception ${throwable.message}"
            )
        }

        GlobalScope.launch (Dispatchers.Main + Job() + CoroutineName("GlobalScopeCoroutine") +exceptionHandler){
            println("xiaozhan running in ${Thread.currentThread()} ${coroutineContext[CoroutineName]}")
            println("xiaozhan Hello Coroutines")
            1 / 0
            println("xiaozhan will not println")
        }
    }


    //子job各自执行launch方法
    private fun case1(){
        val scope = MainScope()
        scope.launch(Job()) {

            this.launch (SupervisorJob() + Dispatchers.Main){
                delay(2000L)
                println("CancelJobActivity job1 finished")
                scope.cancel()
            }

            this.launch (SupervisorJob() + Dispatchers.Main) {
                delay(3000L)
                println("CancelJobActivity job2 finished")
            }
        }
    }

    //其中一个job取消，则父job全部取消
    private fun case2(){
        val scope = MainScope()
        scope.launch {
            launch {
                delay(2000L)
                println("CancelJobActivity jobb1 finished")
                scope.cancel()
            }

            launch {
                delay(3000L)
                println("CancelJobActivity job2 finished")
            }

        }
    }


    private fun exceptionWithJob(){
        val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
            println("catch exception ${throwable.message}")
        }

        //Job 使用时如果其中一个子协程异常关闭时，会通知父类Job关闭协程，并把该父类Job下的所有子Job协程全部关闭

        val mainScope = CoroutineScope(Dispatchers.Main + Job() + exceptionHandler)

        mainScope.launch {
            println("job1 start")
            delay(2000)
            println("job1 end")
        }

        mainScope.launch {
            println("job2 start")
            delay(1000)
            println("job2 end")
            1 / 0
        }

        mainScope.launch {
            println("job3 start")
            delay(2000)
            println("job3 end")
        }

    }

    private fun exceptionWithSupervisorJob(){
        val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
            println("catch exception ${throwable.message}")
        }


        //SupervisorJob 当子类工作协程出现异常时，不会影响其他的子类工作协程，通知给父类Job时，父类Job会忽略此子Job工作协程
        val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob() + exceptionHandler)

        mainScope.launch {
            println("job1 start")
            delay(2000)
            println("job1 end")
        }

        mainScope.launch {
            println("job2 start")
            delay(1000)
            1 / 0
            println("job2 end")
        }

        mainScope.launch {
            println("job3 start")
            delay(2000)
            println("job3 end")
        }

    }




    fun jobCancel(){
        val job1 = MainScope().launch {
            delay(2000)
            println("running in job1")
        }

        MainScope().launch {
            delay(1000)
            job1.cancel()
            println("running in job2")
        }
    }


    /**
     * CancellationException 是一种特殊的Exception,它和Exception的区别在于，如果在协程中抛出CancellationException.除了子协程外并不会影响其他协程
     */
    fun jobSleepCancel() {
        val job1 = MainScope().launch(Dispatchers.IO) {
            Thread.sleep(2000L)
//            yield()   //通过协程挂起点进行中断此协工作
            ensureActive() //通过判断是否存活，抛出 CancellationException 异常进行中断此工作
            println("running in job1")
        }

        MainScope().launch {
            delay(1000)
            job1.cancel()
            println("running in job2")
        }
    }


    private fun cancelExceptionWithJob() {
        val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
            println("catch exception ${throwable.message}")
        }

        val mainScope = CoroutineScope(Dispatchers.Main + Job() + exceptionHandler)

        val job1 = mainScope.launch {
            println("job1 start")
            delay(2000)
            println("job1 end")
        }

//        delay()

        mainScope.launch {
            println("job2 start")
            launch {
                println("job4 start")
                delay(2000)
                println("job4 end")
            }
            delay(1000)
            throw CancellationException()
            println("job2 end")
        }
    }


    /**
     * CompletionHandler类似java中的callback，当Job完成、取消、失败后，调用此handler
     * CompletionHandler持有ChildJob，并注册到父Job上，那么子Job可以监听父Job的取消和完成事件，重而实现事件从上往下传播
     * 如果子Job能够直接或间接的持有父Job的引用，那么当子Job被cancel时，就能直接把事件，从上往下传播，所以cancel事件是双向传播的
     *
     * 而协程框架是通过invokeCompletion方法来建立Job的树形关系
     *
     *
     */
    fun invokeCompletion() {
        val job = MainScope().launch {
            println("job start")
            delay(2000)
            println("job end")
        }
        //当前job注册回调
        job.invokeOnCompletion {
            println("job invokeOnCompletion")
        }
    }

    fun invokeCancelCompletion(){
        val launch = MainScope().launch {
            println("job start")
            delay(2000)
            println("job end")
        }

        MainScope().launch {
            println("cancel launch")
            delay(1000)
            launch.cancel()
        }

        launch.invokeOnCompletion {
            println("job is completion")
        }
    }



    fun testLaunch(){
        println("launch 1")
        lifecycleScope.launch(Dispatchers.Main) {
            println("lifecycleScope launch method")
        }
        println("launch 2")
    }


    suspend fun testUnderStandSuspend(){
        println("Before")

//        suspendCoroutine<Unit> { continuation ->
//            invokeAfterSecond {
//                continuation.resume(Unit)
//            }
//        }

        delay(1000)

        println("After")
    }

    fun invokeAfterSecond(block:() -> Unit){
        thread {
            Thread.sleep(1000)
            block.invoke()
        }
    }

    suspend fun delay(time: Long): Unit =
        suspendCoroutine<Unit> { continuation ->
            executor.schedule({
                              //不可取消
//                continuation.resume(Unit)

                  //可以取消
//                continuation.resumeCancellableWith(Unit,MyException())

                  //返回异常
//                  continuation.resumeWithException(MyException())
            }, time, TimeUnit.MILLISECONDS)
        }

    private val executor =
        Executors.newSingleThreadScheduledExecutor {
            Thread(it, "scheduler").apply {
                isDaemon = true
            }
        }



//    suspend fun requestUser(): UsedWeb {
//        return suspendCancellableCoroutine<UsedWeb> {
//            requestUser { resp ->
//                if (resp.visible){
//
//                }
//            }
//        }
//    }


//    val launcher = rememberLauncherForActivityResult(contract =object : ActivityResultContract() {
//        override fun createIntent(context: Context, input: Any?): Intent {
//          return Intent(context,SecondActivity::class.java)
//         }
//         override fun parseResult(resultCode: Int, intent: Intent?): String {
//           val data = intent?.getStringExtra("data")?:""
//             return data
//         }
//    }, onResult ={
//        result = it
//    })

}